package com.codi.bus.core.fund.service.impl;

import com.codi.base.spring.SpringContextHolder;
import com.codi.base.util.DateUtil;
import com.codi.base.util.ListUtil;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.dao.PortfolioFundOrderDao;
import com.codi.bus.core.domain.PortfolioFundOrder;
import com.codi.bus.core.domain.User;
import com.codi.bus.core.fund.dao.FundDividendChangeDao;
import com.codi.bus.core.fund.domain.FundDividendChange;
import com.codi.bus.core.fund.dto.FundDividendChangeQueryDto;
import com.codi.bus.core.fund.enums.DividendAutoBuyEnum;
import com.codi.bus.core.fund.enums.FundDividendChangeBizTypeEnum;
import com.codi.bus.core.fund.enums.FundDividendChangeStatusEnum;
import com.codi.bus.core.fund.manager.FundDividendChangeManager;
import com.codi.bus.core.fund.service.FundDividendChangeService;
import com.codi.bus.core.service.UserService;
import com.codi.fcloud.ufx.constant.HsConst;
import com.codi.trade.dto.HsDividendMethodTradeRequestDto;
import com.codi.trade.dto.PortfolioSummaryQryDto;
import com.codi.trade.dto.TradeApplyQryDto;
import com.codi.trade.response.HsDividendMethodTradeResponse;
import com.codi.trade.response.HsPortfolioSummaryQryResponse;
import com.codi.trade.response.HsTradeApplyQryResponse;
import com.codi.trade.service.HsDividendMethodTradeService;
import com.codi.trade.service.TradeApplyQueryService;
import com.codi.trade.service.portfolio.HsPortfolioSummaryQryService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 模块名
 *
 * @author spy
 * @version 1.0 2018-01-29
 * @since 1.0
 */
@Slf4j
@Service
public class FundDividendChangeServiceImpl implements FundDividendChangeService {

    @Autowired
    private FundDividendChangeDao fundDividendChangeDao;

    @Autowired
    private FundDividendChangeManager fundDividendChangeManager;

    @Autowired
    private PortfolioFundOrderDao portfolioFundOrderDao;

    @Autowired
    private UserService userService;

    @Autowired
    private TradeApplyQueryService tradeApplyQueryService;

    @Autowired
    private HsPortfolioSummaryQryService hsPortfolioSummaryQryService;

    @Autowired
    private HsDividendMethodTradeService hsDividendMethodTradeService;


    @Override
    @Async
    @Transactional
    public void addPortfolioApplyWait(FundDividendChange record) {
        fundDividendChangeManager.addPortfolioApplyWaitAsync(record);
    }

    @Override
    public void applyPortfolioChange() {
        boolean isEnd = false;

        Integer MAX_PAGE = 100;
        FundDividendChangeQueryDto queryRecord;
        FundDividendChangeService fundDividendChangeService = SpringContextHolder.getBean(FundDividendChangeService.class);


        while (!isEnd) {

            PageHelper.startPage(1, MAX_PAGE);

            queryRecord = FundDividendChangeQueryDto.builder()
                                                    .bizType(FundDividendChangeBizTypeEnum.PORTFOLIO.getKey())
                                                    .status(FundDividendChangeStatusEnum.WAIT_APPLY.getKey())
                                                    .build();
            List<FundDividendChange> fundDividendChanges = fundDividendChangeDao.select(queryRecord);

            PageInfo pageInfo = new PageInfo(fundDividendChanges);

            if (pageInfo.getTotal() == 0) {
                log.info("待处理数为0，等待下次执行");
                return;
            }

            isEnd = pageInfo.isIsLastPage();


            for (int i = 0, j = fundDividendChanges.size(); i < j; i++) {
                FundDividendChange dividendChange = fundDividendChanges.get(i);

                // 组合订单的交易状态
                PortfolioFundOrder order = portfolioFundOrderDao.getByApplyNo(dividendChange.getTradeAllotNo());

                if (order == null) {
                    log.warn("组合订单【{}】不存在", dividendChange.getTradeAllotNo());
                    continue;
                }

                // 确认成功的进行状态修改
                if (order.getStatus().intValue() == GlobalConstant.ORDER_STATUS_CONFIRM.intValue()) {
                    // 发起修改

                    String portfolioAllotNo = dividendChange.getTradeAllotNo();
                    User user = userService.getUser(dividendChange.getUserId());
                    // ta_acco

                    log.info("portfolio allotNo={}", portfolioAllotNo);

                    PortfolioSummaryQryDto portfolioSummaryQryDto = PortfolioSummaryQryDto.builder()
                                                                                          .portfolio_allot_no(portfolioAllotNo)
                                                                                          .client_id(user.getExternalClientId())
                                                                                          .build();

                    List<HsPortfolioSummaryQryResponse> summaryQryResponseList = hsPortfolioSummaryQryService.queryV2(portfolioSummaryQryDto);
                    if (ListUtil.isEmpty(summaryQryResponseList)) {
                        return;
                    }
                    HsPortfolioSummaryQryResponse portfolioSummaryQryResponse = summaryQryResponseList.get(0);

                    String portfolioTradeAcco = portfolioSummaryQryResponse.getTrade_acco();


                    TradeApplyQryDto tradeApplyQryDto = TradeApplyQryDto.builder()
                                                                        .request_num(GlobalConstant.MAX_REQUEST_NUM.toString())
                                                                        .trade_acco(portfolioTradeAcco)
                                                                        .build();

                    List<HsTradeApplyQryResponse> tradeApplyQryResponseList = tradeApplyQueryService.queryV2(tradeApplyQryDto);

                    //fixme 暂时用applyQueryService

                    if (ListUtil.isEmpty(tradeApplyQryResponseList)) {
                        log.warn("portfolio apply qry response is null");
                        return;
                    }

                    for (int k = 0, l = tradeApplyQryResponseList.size(); k < l; k++) {

                        HsTradeApplyQryResponse applyQryResponse = tradeApplyQryResponseList.get(k);
                        log.debug("applyQryResponse={}", applyQryResponse);

                        // change
                        HsDividendMethodTradeRequestDto changeDto = HsDividendMethodTradeRequestDto.builder()
                                                                                                   .ta_acco(applyQryResponse.getTa_acco())
                                                                                                   .trade_acco(applyQryResponse.getTrade_acco())
                                                                                                   .password(HsConst.NOPASSWORD)
                                                                                                   .fund_code(applyQryResponse.getFund_code())
                                                                                                   .share_type(applyQryResponse.getShare_type())
                                                                                                   .auto_buy(DividendAutoBuyEnum.REINVESTMENT.getKey())
                                                                                                   .build();

                        HsDividendMethodTradeResponse response = hsDividendMethodTradeService.change(changeDto);


                        if (response.getSuccess()) {
                            Date applyDate = null;
                            if (!Strings.isNullOrEmpty(response.getApply_date())) {
                                applyDate = DateUtil.parse(response.getApply_date(), "yyyyMMdd");
                            }

                            log.info("dividend change apply date={}", applyDate);
                            // update dividend change


                            FundDividendChange record = FundDividendChange.builder()
                                                                          .id(dividendChange.getId())
                                                                          .tradeAcco(applyQryResponse.getTrade_acco())
                                                                          .taAcco(applyQryResponse.getTa_acco())
//                                                                          .fundCode(applyQryResponse.getFund_code())
                                                                          .shareType(applyQryResponse.getShare_type())
                                                                          .allotNo(response.getAllot_no())
                                                                          .status(FundDividendChangeStatusEnum.APPLY_SUC.getKey())
                                                                          .applyDate(applyDate)
                                                                          .lastUpdateDate(new Date())
                                                                          .build();

                            fundDividendChangeService.updateInNewTrans(record);
                            log.info("dividend change update={}", record);
                        }


                        //-----------------------------------------------
                        // order confirm end

                        continue;
                    }

                    // 确认失败的直接标记失败
                    if (order.getStatus().intValue() == GlobalConstant.ORDER_STATUS_CANCEL.intValue()
                        || (order.getStatus().intValue() == GlobalConstant.ORDER_STATUS_CONFIRM_FAIL.intValue())) {
                        log.info("portfolio allotNo={} is fail so update fail", dividendChange.getTradeAllotNo());
                        FundDividendChange updateRecord = FundDividendChange.builder()
                                                                            .id(dividendChange.getId())
                                                                            .build();
                        fundDividendChangeService.changeFail(updateRecord);
                    }

                }


            }
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void changeFail(FundDividendChange record) {
        Preconditions.checkNotNull(record);
        Preconditions.checkNotNull(record.getId());

        FundDividendChange updateRecord = FundDividendChange.builder()
                                                            .id(record.getId())
                                                            .status(FundDividendChangeStatusEnum.FAIL.getKey())
                                                            .lastUpdateDate(new Date())
                                                            .build();

        fundDividendChangeDao.updateByPrimaryKeySelective(updateRecord);

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateInNewTrans(FundDividendChange record) {
        Preconditions.checkNotNull(record);
        Preconditions.checkNotNull(record.getId());

        record.setLastUpdateDate(new Date());

        fundDividendChangeDao.updateByPrimaryKeySelective(record);
    }
}
